using CfgTable;
using IQIGame.Onigao.Framework;
using IQIGame.Onigao.Game;
using NetProtocol.Client;
using NetProtocol.POD;
using System;
using System.Collections.Generic;

namespace IQIGame.Onigao.GamePlay
{
    public class MallModule : Singleton<MallModule>, CNetMall
    {
        private MallModule() { }
        private MallModuleData MallData => GameDataCenter.PlayerData.Mall;
        public void InitModule(PlayerPOD playerPOD)
        {
            MallModuleData mallModule = new MallModuleData(playerPOD.mallBuyCountRecords, playerPOD.mallStartSellTime, playerPOD.payCount, playerPOD.monthCard);
            GameDataCenter.PlayerData.Mall = mallModule;
        }

        public void ClearModule()
        {
            GameDataCenter.PlayerData.Mall = null;
        }

        #region Net层
        public static CNetMall NetCore => Instance;
        ISession CNetMall.GetSession()
        {
            return GameServerModule.Instance.CurrSession;
        }

        void CNetMall.SC_notifyMallRefresh(ISession session, Dictionary<int, int> mallBuyCountRecords)
        {
            this.MallData.RefreshMallBuyCountRecords(mallBuyCountRecords);
            MsgDispatcher.Broadcast(MsgEventType.MallItemUpdateBuyCountRecords);
        }

        void CNetMall.SC_notifyMallStartSellTime(ISession session, Dictionary<int, int> mallStartSellTime)
        {
            this.MallData.RefreshMallStartSellTime(mallStartSellTime);
            MsgDispatcher.Broadcast(MsgEventType.MallItemUpdateStartSellTime);
        }

        void CNetMall.SC_notifyPayInfo(ISession session, Dictionary<int, int> payCount)
        {
            this.MallData.RefreshPayCount(payCount);
            MsgDispatcher.Broadcast(MsgEventType.MallItemUpdatePayCount);
        }

        void CNetMall.SC_notifyMonthCard(ISession session, Dictionary<int, int> monthCard)
        {
            var oldMonthCard = this.MallData.monthCard;
            this.MallData.RefreshMonthCard(monthCard);
            this.BroadcastMonthCardChange(monthCard, oldMonthCard);
        }

        void BroadcastMonthCardChange(Dictionary<int, int> monthCard, Dictionary<int, int> oldMonthCard)
        {
            foreach (var cid2Expire in monthCard)
            {
                bool isChanged = !oldMonthCard.TryGetValue(cid2Expire.Key, out var oldExpire) || cid2Expire.Value != oldExpire;
                if (isChanged)
                {
                    MsgDispatcher.Broadcast<int>(MsgEventType.MallItemMonthCardChanged, cid2Expire.Key);
                }
            }
        }

        void CNetMall.SC_notifyRecharge(ISession session, NotifyRechargePOD notifyRechargePOD)
        {
            NoticeModule.ShowUIItemGet(notifyRechargePOD.unsafe_exBonus);
            MsgDispatcher.Broadcast<int>(MsgEventType.MallItemRechargeSuccess, notifyRechargePOD.goodsId);
        }
        #endregion

        #region 网络数据获取
        public int GetMonthCardInvlidTime(int monthCardId)
        {
            if (!this.MallData.monthCard.TryGetValue(monthCardId, out var invlidTime))
            {
                return 0;
            }
            return invlidTime;
        }


        #endregion

        /// <summary>
        /// 获取商城资产条显示的道具列表
        /// </summary>
        public int[] GetMallMoneyPanelItemList(int mallTypeCid)
        {
            if (!TableCenter.mallItem.MallItemMap.TryGetValue(mallTypeCid, out var rMallItemList))
            {
                LogGame.LogError($"mallItem表中不存在MallType={mallTypeCid}的相关商品数据！！！");
                return null;
            }

            List<int> result = Game.ListPool<int>.Get();
            foreach (var mallItem in rMallItemList)
            {
                var cfgMallItem = TableCenter.mallItem.Get(mallItem);
                if (cfgMallItem.SellType == MallSellType.Free) continue;
                int tempItemId = 0;
                if (cfgMallItem.SellType == MallSellType.Item)
                {
                    tempItemId = cfgMallItem.Price[0];
                }
                else
                {
                    tempItemId = ItemConst.ItemCid_PayPoint_ForShow;
                }
                if (tempItemId == 0 || result.Contains(tempItemId))
                {
                    continue;
                }
                result.Add(tempItemId);

            }
            var rArray = result.ToArray();
            Game.ListPool<int>.Put(result);
            return rArray;
        }

        public bool CheckMallTypeIsOpen(MallOriginalType originalType, int mainType)
        {
            var cids = TableCenter.mallType.GetMallSubTypeCids(originalType, mainType);
            foreach (var cid in cids)
            {
                if (this.CheckMallTypeIsOpen(cid))
                {
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// 检查商城是否开启
        /// </summary>
        public bool CheckMallTypeIsOpen(int mallTypeCid)
        {
            var cfgMallType = TableCenter.mallType.Get(mallTypeCid);
            if (this.CheckMallTypeIsOpenByTimeLimit(cfgMallType))
            {
                if (this.CheckMallTypeIsOpenByNormalActivity(cfgMallType))
                {
                    return true;
                }
                return this.CheckMallTypeIsOpenByMallItems(mallTypeCid);
            }
            return false;
        }

        private bool CheckMallTypeIsOpenByTimeLimit(CfgMallType cfgMallType)
        {
            if (cfgMallType.TimeLimitType == MallType_TimeLimitType.Time)
            {
                return this.CheckTimeLimitIsOpen(cfgMallType.TimeLimitOpen, cfgMallType.TimeLimitEnd);
            }
            return true;
        }

        private bool CheckTimeLimitIsOpen(string timeOpen, string timeClose)
        {
            long tempTick = this.DateTimeToTicks(timeOpen);
            long nowTick = GameServerModule.Instance.ServerTime.Ticks;
            if (nowTick >= tempTick)
            {
                tempTick = this.DateTimeToTicks(timeClose);
                return nowTick <= tempTick;
            }
            return false;
        }

        private bool CheckMallTypeIsOpenByNormalActivity(CfgMallType cfgMallType)
        {
            if (cfgMallType.OriginalType == MallOriginalType.Mall && cfgMallType.Type == (int)MallNormalMainType.MallActive)
            {
                // TODO 推荐 需要判断是否需要在显示
                return true;
            }
            return false;
        }

        private bool CheckMallTypeIsOpenByMallItems(int mallTypeCid)
        {
            if (TableCenter.mallItem.MallItemMap.TryGetValue(mallTypeCid, out var mallItemCids))
            {
                for (int i = 0; i < mallItemCids.Count; i++)
                {
                    if (this.CheckMallItemIsCanShow(mallItemCids[i]))
                    {
                        return true;
                    }
                }
            }
            return false;
        }

        public bool CheckMallItemIsCanShow(int mallItemCid)
        {
            var cfgMallItem = TableCenter.mallItem.Get(mallItemCid);
            if (this.CheckMallItemTimeLimitIsOpen(cfgMallItem))
            {
                return this.CheckConditionIsCanShow(cfgMallItem);
            }
            return false;
        }

        private bool CheckConditionIsCanShow(CfgMallItem cfgMallItem)
        {
            return this.CheckIsReachCondition(cfgMallItem.ShowConditionId);
        }

        private bool CheckIsReachCondition(int conditionCid)
        {
            if (conditionCid > 0)
            {
                // TODO 目前加入一个判断，还没具体实现返回条件的数据
                var result = ConditionSystemUtil.Check(conditionCid);
                return result.Item1;
            }
            return true;
        }

        /// <summary>
        /// 该付费档位是否为首次付费
        /// </summary>
        public bool IsFirstRecharge(int mallItemCid)
        {
            return this.GetRechargePayCount(mallItemCid) == 0;
        }

        public int GetRechargePayCount(int mallItemCid)
        {
            var dic = this.MallData.payCount;
            return dic.TryGetValue(mallItemCid, out int count) ? count : 0;
        }

        public int GetBuyCount(int mallItemCid)
        {
            var dic = this.MallData.mallBuyCountRecords;
            return dic.TryGetValue(mallItemCid, out int count) ? count : 0;
        }

        private DateTime ParseDate(string strDatetime)
        {
            if (string.IsNullOrEmpty(strDatetime))
            {
                throw new System.FormatException("时间字符串为空");
            }
            if (!GameServerModule.Instance.TryParseDateStr(strDatetime, out var dateTime))
            {
                throw new System.FormatException("时间字符串格式错误");
            }
            return dateTime;
        }

        private long DateTimeToTicks(string strDatetime)
        {
            var dateTime = ParseDate(strDatetime);
            return dateTime.Ticks;
        }

        public int GetMallLimitSeconds(CfgMallItem cfgMallItem)
        {
            return cfgMallItem.TimeLimitType switch
            {
                MallTimeLimitType.Time => this.GetMallLimitSecondsByTimeStr(cfgMallItem),
                MallTimeLimitType.SaleTime => this.GetMallLimitSecondsBySaleTime(cfgMallItem),
                _ => 0
            };
        }

        private int GetMallLimitSecondsByTimeStr(CfgMallItem cfgMallItem)
        {
            var endDate = this.ParseDate(cfgMallItem.TimeLimitEnd);
            var tempSpan = endDate - GameServerModule.Instance.ServerTime;
            return (int)tempSpan.TotalSeconds;
        }

        private int GetMallLimitSecondsBySaleTime(CfgMallItem cfgMallItem)
        {
            if (this.MallData.mallStartSellTime.TryGetValue(cfgMallItem.Id, out var startSecond))
            {
                var tempSecond = startSecond + cfgMallItem.SalesTime - GameServerModule.Instance.ServerTimestamp;
                return tempSecond;
            }
            return 0;
        }

        private bool CheckMallItemTimeLimitIsOpen(CfgMallItem cfgMallItem)
        {
            return cfgMallItem.TimeLimitType switch
            {
                MallTimeLimitType.Time => this.CheckTimeLimitIsOpen(cfgMallItem.TimeLimitOpen, cfgMallItem.TimeLimitEnd),
                MallTimeLimitType.SaleTime => this.CheckMallItemSaleTimeIsOpen(cfgMallItem),
                _ => true,
            };
        }

        private bool CheckMallItemSaleTimeIsOpen(CfgMallItem cfgMallItem)
        {
            if (this.MallData.mallStartSellTime.TryGetValue(cfgMallItem.Id, out var startSecond))
            {
                var endSecond = startSecond + cfgMallItem.SalesTime;
                var nowSecond = GameServerModule.Instance.ServerTimestamp;
                return (nowSecond >= startSecond && nowSecond < endSecond);
            }
            return false;
        }

        public bool CheckConditionIsCanBuy(CfgMallItem cfgMallItem)
        {
            return this.CheckIsReachCondition(cfgMallItem.ConditionId);
        }
    }
}
